
#include "Sqlite3Stmt.h"

#include "db/sqlite3/sqlite3.24.0/sqlite3.h"


Sqlite3Stmt::~Sqlite3Stmt()
{
    sqlite3_finalize(stmt_);
}

bool Sqlite3Stmt::perpare(const std::string& sql)
{
    int ret = sqlite3_prepare_v2(handle_, sql.c_str(), sql.size(), &stmt_, NULL);
    if (SQLITE_OK == ret) {
        col_count_ = sqlite3_column_count(stmt_);
    }
    return SQLITE_OK == ret;
}

bool Sqlite3Stmt::reset()
{
    return sqlite3_reset(stmt_) == SQLITE_OK;
}

bool Sqlite3Stmt::clear_bind()
{
    return sqlite3_clear_bindings(stmt_) == SQLITE_OK;
}

int64_t Sqlite3Stmt::exec()
{
    int ret = sqlite3_step(stmt_);
    if (ret == SQLITE_ROW) 
    {
        printf("sqlite3 exec misuse\n");
        assert(0);
        return -1;
    }
    if (ret == SQLITE_DONE) {
        return sqlite3_changes(handle_);
    }
    return -1;
}

bool Sqlite3Stmt::query(DBRows& rows)
{
    int ret = sqlite3_step(stmt_);

    if (ret != SQLITE_ROW && ret != SQLITE_DONE)
    {
        return false;
    }
    if (ret == SQLITE_DONE) {
        return true;
    }

    std::vector<std::shared_ptr<row_meta_data>> fields;
    for (size_t i = 0; i < col_count_; ++i)
    {
        auto m = std::make_shared<row_meta_data>();
        m->name = sqlite3_column_name(stmt_, i);
        m->origin_name = sqlite3_column_origin_name(stmt_, i);
        m->origin_type = sqlite3_column_type(stmt_, i);
       
        fields.emplace_back(m);
    }
    do 
    {
        DBRow row;
        for (size_t i = 0; i < col_count_; ++i)
        {
            int byteslen = sqlite3_column_bytes(stmt_, i);
            const char* bytes = (const char*)sqlite3_column_blob(stmt_, i);
            std::string str(bytes, byteslen);
            row.row_.emplace_back(DBValue(fields[i], str));
        }
        rows.rows_.emplace_back(row);
        ret = sqlite3_step(stmt_);
    } while (ret != SQLITE_DONE);
    return true;
}

bool Sqlite3Stmt::bind(int index, std::nullptr_t)
{
    return sqlite3_bind_null(stmt_, index) == SQLITE_OK;
}

bool Sqlite3Stmt::bind(int index, bool val)
{
    return sqlite3_bind_int(stmt_, index, int(val)) == SQLITE_OK;
}

bool Sqlite3Stmt::bind(int index, int8_t val)
{
    return sqlite3_bind_int(stmt_, index, val) == SQLITE_OK;
}

bool Sqlite3Stmt::bind(int index, int16_t val)
{
    return sqlite3_bind_int(stmt_, index, val) == SQLITE_OK;
}

bool Sqlite3Stmt::bind(int index, int32_t val)
{
    return sqlite3_bind_int64(stmt_, index, val) == SQLITE_OK;
}

bool Sqlite3Stmt::bind(int index, int64_t val)
{
    return sqlite3_bind_int64(stmt_, index, val) == SQLITE_OK;
}

bool Sqlite3Stmt::bind(int index, uint8_t val)
{
    return sqlite3_bind_int(stmt_, index, val) == SQLITE_OK;
}

bool Sqlite3Stmt::bind(int index, uint16_t val)
{
    return sqlite3_bind_int(stmt_, index, val) == SQLITE_OK;
}

bool Sqlite3Stmt::bind(int index, uint32_t val)
{
    return sqlite3_bind_int64(stmt_, index, val) == SQLITE_OK;
}

bool Sqlite3Stmt::bind(int index, uint64_t val)
{
    return sqlite3_bind_int64(stmt_, index, val) == SQLITE_OK;
}

bool Sqlite3Stmt::bind(int index, float val)
{
    return sqlite3_bind_double(stmt_, index, val) == SQLITE_OK;
}

bool Sqlite3Stmt::bind(int index, double val)
{
    return sqlite3_bind_double(stmt_, index, val) == SQLITE_OK;
}

bool Sqlite3Stmt::bind(int index, const std::string& val)
{
    return sqlite3_bind_text(stmt_, index, val.c_str(), val.size(), SQLITE_TRANSIENT) == SQLITE_OK;
}

bool Sqlite3Stmt::bind(int index, const char* val)
{
    return sqlite3_bind_text(stmt_, index, val, -1, SQLITE_TRANSIENT) == SQLITE_OK;
}

bool Sqlite3Stmt::bind(int index, const unsigned char* val)
{
    return sqlite3_bind_text(stmt_, index, (const char*)val, -1, SQLITE_TRANSIENT) == SQLITE_OK;
}

bool Sqlite3Stmt::bind(int index, const void* val, size_t len)
{
    return sqlite3_bind_blob(stmt_, index, val, len, SQLITE_TRANSIENT) == SQLITE_OK;
}
